<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script src="lodash.min.js"></script>
		<script>
			// 分配来源对象的可枚举属性到目标对象上，该方法不会获取原型链上的属性，而assignIn可以获取
			function Foo() {
			  this.a = 1;
			}
			function Bar() {
			  this.c = 3;
			}
			Foo.prototype.b = 2;
			Bar.prototype.d = 4;
			_.assign({ 'a': 0 }, new Foo, new Bar);
			// => { 'a': 1, 'c': 3 }
			
			
			// 创建一个对象，原型继承 参数1（通常是原型函数），参数2支持对创建的对象添加自定义属性
			function Shape() {
			  this.x = 0;
			  this.y = 0;
			}
			function Circle() {
			  Shape.call(this);
			}
			Circle.prototype = _.create(Shape.prototype, {
			  'constructor': Circle
			});
			console.log(Circle.prototype);
			var circle = new Circle;
			circle instanceof Circle;
			// => true
			circle instanceof Shape;
			// => true
			
			
			// 创建一个object对象自身可枚举属性的键值对数组，toPairsIn可以获取Foo.prototype.c；类似的有_.functions、_.functionsIn，但他只能面向函数
			function Foo() {
			  this.a = 1;
			  this.b = 2;
			}
			Foo.prototype.c = 3;
			_.toPairs(new Foo);
			// => [['a', 1], ['b', 2]] (iteration order is not guaranteed)


			// 分配来源对象的可枚举属性到目标对象所有解析为 undefined 的属性上。 一旦设置了相同属性的值，后续的将被忽略掉。
			_.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
			// => { 'a': 1, 'b': 2 }
			
			// 此处不使用deep的话，第二个对象会被忽略，因为2个对象键都是a
			console.log(_.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }));
			// => { 'a': { 'b': 2, 'c': 3 } }
			
			
			// 这个方法类似_.find 。 除了它返回最先被 predicate 判断为真值的元素 key，而不是元素本身。类似的有findLastKey反向查找
			var users = {
			  'barney':  { 'age': 36, 'active': true },
			  'fred':    { 'age': 40, 'active': false },
			  'pebbles': { 'age': 1,  'active': true }
			};
			_.findKey(users, function(o) { return o.age < 40; });
			// => 'barney' (iteration order is not guaranteed)
			
			
			// 这个方法类似_.forIn。 除了它是反方向开始遍历object的。类似的有forOwn、forOwnRight，他不会遍历原型链的属性
			function Foo() {
			  this.a = 1;
			  this.b = 2;
			}
			Foo.prototype.c = 3;
			_.forInRight(new Foo, function(value, key) {
			  console.log(key);
			});
			// => 输出 'c', 'b', 然后 'a'， `_.forIn` 会输出 'a', 'b', 然后 'c'。
			
			
			// _.get(object, path, [defaultValue])，根据 object对象的path路径获取值（不含原型链属性）。 如果解析 value 是 undefined 会以 defaultValue 取代，可以安全的取值
			_.get( { 'a': [{ 'b': { 'c': 3 } }] }, 'a.b.c', 'default');
			// => 'default'
			
			// 这个方法类似_.get， 除了如果解析到的值是一个函数的话，就绑定 this 到这个函数并返回执行后的结果。
			var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(0) } }] };
			_.result(object, 'a[0].b.c1');
			// => 3
			console.log(_.result(object, 'a[0].b.c2'),_.constant(0));
			// => 4
			_.result(object, 'a[0].b.c3', 'default');
			// => 'default'
			
			
			// 设置 object对象中对应 path 属性路径上的值，如果path不存在，则创建。 缺少的索引属性会创建为数组，而缺少的属性会创建为对象。 使用_.setWith 定制path创建。
			var object = { 'a': [{ 'b': { 'c': 3 } }] };
			_.set(object, 'a[0].b.c', 4);
			// => 4
			_.set(object, ['x', '0', 'y', 'z'], 5);
			// => 5
			console.log(_.setWith({}, '[0][1]', 'a', Object),_.set({}, '[0][1]', 'a'));
			
			
			// .has(object, path)  检查 path 是否是object对象（含原型链上的属性）的直接属性。
			var object = _.create({ 'a': _.create({ 'b': 2 }) });
			_.hasIn(object, 'a');
			// => true
			_.hasIn(object, 'a.b');
			// => true
			_.hasIn(object, ['a', 'b']);
			// => true
			_.hasIn(object, 'b');
			// => false
			
			
			// 键值颠倒,如果 object 有重复的值，后面的值会覆盖前面的值。
			var object = { 'a': 1, 'b': 2, 'c': 1 };
			_.invert(object);
			// => { '1': 'c', '2': 'b' }
			
			// 这个方法类似_.invert，除了倒置对象 是 collection（集合）中的每个元素经过 iteratee（迭代函数） 处理后返回的结果,以及重复值会打包成数组
			var object = { 'a': 1, 'b': 2, 'c': 1 };
			_.invertBy(object);
			// => { '1': ['a', 'c'], '2': ['b'] }
			_.invertBy(object, function(value) {
			  return 'group' + value;
			});
			// => { 'group1': ['a', 'c'], 'group2': ['b'] }
			
			
			// 创建一个 object 自身 和 继承的可枚举属性名为数组。
			function Foo() {
			  this.a = 1;
			  this.b = 2;
			}
			Foo.prototype.c = 3;
			_.keysIn(new Foo);
			// => ['a', 'b', 'c'] (iteration order is not guaranteed)
			
			
			// _.mapValues(object, [iteratee=_.identity])创建一个对象，这个对象的key与object对象相同，值是通过 iteratee 运行 object 中每个自身可枚举属性名字符串产生的。
			var users = {
			  'fred':    { 'user': 'fred',    'age': 40 },
			  'pebbles': { 'user': 'pebbles', 'age': 1 }
			};
			_.mapValues(users, function(o) { return o.age; });
			// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
			_.mapValues(users, 'age');
			// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
			// _.mapKeys(object, [iteratee=_.identity])  反向版_.mapValues。 这个方法创建一个对象，对象的值与object相同，并且 key 是通过 iteratee 运行 object 中每个自身可枚举属性名字符串 产生的
			_.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
			  return key + value;
			});
			// => { 'a1': 1, 'b2': 2 }
			
			
			// 该方法类似_.assign（合并对象）， 
			// 除了它递归合并 sources 来源对象自身和继承的可枚举属性到 object 目标对象。数组和普通对象会递归合并，其他对象和值会被直接分配覆盖。源对象从从左到右分配。后续的来源对象属性会覆盖之前分配的属性。
			// _.mergeWith(object, sources, customizer)方法类似_.merge，除了它接受一个 customizer，调用以产生目标对象和来源对象属性的合并值，customizer(objValue, srcValue) 
			var object = {
			  'a': [{ 'b': 2 }, { 'd': 4 }]
			};
			var other = {
			  'a': [{ 'c': 3 }, { 'e': 5 }]
			};
			_.merge(object, other);
			// => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
			
			
			// 可以理解为删除object对象的属性
			var object = { 'a': 1, 'b': '2', 'c': 3 };
			_.omit(object, ['a', 'c']);
			// => { 'b': '2' }
			
			// 删除函数返回true的对象
			var object = { 'a': 1, 'b': '2', 'c': 3 };
			_.omitBy(object, _.isNumber);
			// => { 'b': '2' }
			
			
			// 挑选对象属性组成对象
			var object = { 'a': 1, 'b': '2', 'c': 3 };
			_.pick(object, ['a', 'c']);
			// => { 'a': 1, 'c': 3 }
			
			// 挑选函数返回true的属性
			var object = { 'a': 1, 'b': '2', 'c': 3 };
			_.pickBy(object, _.isNumber);
			// => { 'a': 1, 'c': 3 }
			
		</script>
	</body>
</html>